home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / shwdib.zip / DRAWDIB.C < prev    next >
C/C++ Source or Header  |  1993-07-26  |  36KB  |  979 lines

  1. /*******************************************************************************
  2.  *                                                                             *
  3.  *  MODULE      : DrawDIB.c                                                    *
  4.  *                                                                             *
  5.  *  PURPOSE     : Handles most of the SHOWDIB's DIB drawing and clipboard      *
  6.  *                operations.                                                  *
  7.  *                                                                             *
  8.  *  FUNCTIONS   :                                                              *
  9.  *                PrintDIB()             -  Sets the current DIB bits to the   *
  10.  *                                          printer DC.                        *
  11.  *                                                                             *
  12.  *                AppPaint()             -  Sets the DIB/bitmap bits on the    *
  13.  *                                          screen or the given device.        *
  14.  *                                                                             *
  15.  *                DrawSelect()           -  Draws selected clip rectangle on   *
  16.  *                                          the DC/screen.                     *
  17.  *                                                                             *
  18.  *                NormalizeRect()        -  Swaps reversed rectangle coords.   *
  19.  *                                                                             *
  20.  *                TrackMouse()           -  Draws rubberbanding rectangle and  *
  21.  *                                          displays it's dimensions.          *
  22.  *                                                                             *
  23.  *                BandDIB()              -  Outputs DIB in bands to device.    *
  24.  *                                                                             *
  25.  *                SizeWindow()           -  Sizes app. window based on client  *
  26.  *                                          dimensions and style.              *
  27.  *                                                                             *
  28.  *                GetRealClientRect()    -  Calculates client rectangle dimen- *
  29.  *                                          sions if scrollbars are present.   *
  30.  *                                                                             *
  31.  *                SetScrollRanges()      -  Sets global scroll ranges.         *
  32.  *                                                                             *
  33.  *                CopyHandle()           -  Makes a copy of memory block.      *
  34.  *                                                                             *
  35.  *                CopyPalette()          -  Makes a copy of the GDI logical    *
  36.  *                                          palette.                           *
  37.  *                                                                             *
  38.  *                CopyBitmap()           -  Copies given bitmap to another.    *
  39.  *                                                                             *
  40.  *                CropBitmap()           -  Crops a bitmap to the given size.  *
  41.  *                                                                             *
  42.  *                RenderFormat()         -  renders currently displayed DIB    *
  43.  *                                          in CF_BITMAP or CF_DIB format.     *
  44.  *                                                                             *
  45.  *                RealizeDibFormat()     -  Realizes the DIB in given format.  *
  46.  *                                                                             *
  47.  *                ErrMsg()               -  Pops an error message to user.     *
  48.  *                                                                             *
  49.  *                fDialog()              -  Displays a dialog box.             *
  50.  *                                                                             *
  51.  *                AppAbout()             -  Shows the About.. dialog box.      *
  52.  *                                                                             *
  53.  *******************************************************************************/
  54. // COPYRIGHT:
  55. //
  56. //   (C) Copyright Microsoft Corp. 1992.  All rights reserved.
  57. //
  58. //   You have a royalty-free right to use, modify, reproduce and
  59. //   distribute the Sample Files (and/or any modified version) in
  60. //   any way you find useful, provided that you agree that
  61. //   Microsoft has no warranty obligations or liability for any
  62. //   Sample Application Files which are modified.
  63. #include <windows.h>
  64. #include <io.h>
  65. #include <stdio.h>
  66. #include "showdib.h"
  67.  
  68. POINT ptSize;       /* Stores DIB dimensions                   */
  69.  
  70. /****************************************************************************
  71.  *                                                                          *
  72.  *  FUNCTION   :  PrintDIB(HWND hWnd, HDC hDC, int x, int y, int dx, int dy)*
  73.  *                                                                          *
  74.  *  PURPOSE    :  Set the DIB bits to the printer DC.                       *
  75.  *                                                                          *
  76.  ****************************************************************************/
  77.  
  78.  
  79. void PrintDIB (hWnd, hDC, x, y, dx, dy)
  80. HWND hWnd;
  81. HDC hDC;
  82. int x, y;
  83. int dx, dy;
  84. {
  85.    BITMAPINFOHEADER bi;
  86.    int dibX, dibY;
  87.    int dibDX, dibDY;
  88.  
  89.    if (!bLegitDraw)
  90.       return;
  91.    DibInfo(hbiCurrent, &bi);
  92.    if (IsRectEmpty(&rcClip))
  93.    {
  94.       dibX = 0;
  95.       dibY = 0;
  96.       dibDX = (int)bi.biWidth;
  97.       dibDY = (int)bi.biHeight;
  98.    }
  99.    else
  100.    {
  101.       dibX = rcClip.left;
  102.       dibY = (int)bi.biHeight - 1 - rcClip.bottom;
  103.       dibDX = rcClip.right - rcClip.left;
  104.       dibDY = rcClip.bottom - rcClip.top;
  105.    }
  106.    if (hdibCurrent)
  107.    {
  108.       /* Stretch the DIB to printer DC */
  109.       StretchDibBlt(hDC, x, y, dx, dy, hdibCurrent, dibX, dibY, dibDX, dibDY,
  110.                     SRCCOPY);
  111.    }
  112.    else if (achFileName[0])
  113.    {
  114.       SetMapMode(hDC, MM_ANISOTROPIC);
  115.       SetViewportOrg(hDC, x, y);
  116.       SetViewportExt(hDC, dx, dy);
  117.       BandDIB(hWnd, hDC, 0, 0);
  118.    }
  119. }
  120.  
  121. /****************************************************************************
  122.  *                                                                          *
  123.  *  FUNCTION   :  AppPaint(HWND hWnd, HDC hDC, int x, int y)                *
  124.  *                                                                          *
  125.  *  PURPOSE    :  Sets the DIB/bitmap bits on the screen or the given device*
  126.  *                                                                          *
  127.  ****************************************************************************/
  128.  
  129.  
  130. void AppPaint (hWnd, hDC, x, y)
  131. HWND hWnd;
  132. HDC hDC;
  133. int x, y;
  134. {
  135.    HPALETTE hpalT;
  136.    BITMAPINFOHEADER bi;
  137.  
  138.    SetWindowOrg(hDC, x, y);
  139.    SetBkMode(hDC, wTransparent);
  140.    if (bLegitDraw)
  141.    {
  142.       hpalT = SelectPalette(hDC, hpalCurrent, FALSE);
  143.       RealizePalette(hDC);
  144.       if (hbmCurrent && !bDIBToDevice)
  145.       {
  146.          DrawBitmap(hDC, 0, 0, hbmCurrent, SRCCOPY);
  147.       }
  148.       else if (hdibCurrent)
  149.       {
  150.          DibInfo(hdibCurrent, &bi);
  151.          DibBlt(hDC, 0, 0, (int)bi.biWidth, (int)bi.biHeight, hdibCurrent, 0, 0
  152.                 , SRCCOPY);
  153.       }
  154.       else if (achFileName[0])
  155.       {
  156.          BandDIB(hWnd, hDC, 0, 0);
  157.       }
  158.       SelectPalette(hDC, hpalT, FALSE);
  159.    }
  160.    DrawSelect(hDC, TRUE);
  161. }
  162.  
  163. /****************************************************************************
  164.  *                                                                          *
  165.  *  FUNCTION   :  DrawSelect(HDC hdc, BOOL fDraw)                           *
  166.  *                                                                          *
  167.  *  PURPOSE    :  Draws the selected clip rectangle with its dimensions on  *
  168.  *                the DC/screen                                             *
  169.  *                                                                          *
  170.  ****************************************************************************/
  171.  
  172.  
  173. void DrawSelect (hdc, fDraw)
  174. HDC hdc;
  175. BOOL fDraw;
  176. {
  177.    char sz[80];
  178.    DWORD dw;
  179.    int x, y, len, dx, dy;
  180.    HDC hdcBits;
  181.    HBITMAP hbm;
  182.  
  183.    if (!IsRectEmpty(&rcClip))
  184.    {
  185.  
  186.       /* If a rectangular clip region has been selected, draw it */
  187.       PatBlt(hdc, rcClip.left, rcClip.top, rcClip.right - rcClip.left, 1,
  188.              DSTINVERT);
  189.       PatBlt(hdc, rcClip.left, rcClip.bottom, 1, -(rcClip.bottom - rcClip.top),
  190.              DSTINVERT);
  191.       PatBlt(hdc, rcClip.right - 1, rcClip.top, 1, rcClip.bottom - rcClip.top,
  192.              DSTINVERT);
  193.       PatBlt(hdc, rcClip.right, rcClip.bottom - 1, -(rcClip.right - rcClip.left
  194.              ), 1, DSTINVERT);
  195.  
  196.       /* Format the dimensions string ...*/
  197.       wsprintf(sz, "%dx%d", rcClip.right - rcClip.left, rcClip.bottom - rcClip.
  198.                top);
  199.       len = lstrlen(sz);
  200.  
  201.       /* ... and center it in the rectangle */
  202.       dw = GetTextExtent(hdc, sz, len);
  203.       dx = LOWORD (dw);
  204.       dy = HIWORD (dw);
  205.       x = (rcClip.right + rcClip.left - dx) / 2;
  206.       y = (rcClip.bottom + rcClip.top - dy) / 2;
  207.       hdcBits = CreateCompatibleDC(hdc);
  208.       SetTextColor(hdcBits, 0xFFFFFFL);
  209.       SetBkColor(hdcBits, 0x000000L);
  210.  
  211.       /* Output the text to the DC */
  212.       if (hbm = CreateBitmap(dx, dy, 1, 1, NULL))
  213.       {
  214.          hbm = SelectObject(hdcBits, hbm);
  215.          ExtTextOut(hdcBits, 0, 0, 0, NULL, sz, len, NULL);
  216.          BitBlt(hdc, x, y, dx, dy, hdcBits, 0, 0, SRCINVERT);
  217.          hbm = SelectObject(hdcBits, hbm);
  218.          DeleteObject(hbm);
  219.       }
  220.       DeleteDC(hdcBits);
  221.    }
  222. }
  223. /****************************************************************************
  224.  *                                                                          *
  225.  *  FUNCTION   : NormalizeRect(RECT *prc)                                   *
  226.  *                                                                          *
  227.  *  PURPOSE    : If the rectangle coordinates are reversed, swaps them      *
  228.  *                                                                          *
  229.  ****************************************************************************/
  230.  
  231.  
  232. void PASCAL NormalizeRect (prc)
  233. RECT *prc;
  234. {
  235.    if (prc->right < prc->left)
  236.       SWAP(prc->right,prc->left);
  237.    if (prc->bottom < prc->top)
  238.       SWAP(prc->bottom,prc->top);
  239. }
  240.  
  241. /****************************************************************************
  242.  *                                                                          *
  243.  *  FUNCTION   : TrackMouse(HWND hwnd, POINT pt)                            *
  244.  *                                                                          *
  245.  *  PURPOSE    : Draws a rubberbanding rectangle and displays it's          *
  246.  *               dimensions till the mouse button is released               *
  247.  *                                                                          *
  248.  ****************************************************************************/
  249.  
  250.  
  251. void TrackMouse (hwnd, pt)
  252. HWND hwnd;
  253. POINT pt;
  254. {
  255.    HDC hdc;
  256.    MSG msg;
  257.    POINT ptOrigin;
  258.    RECT rcClient;
  259.  
  260.    hdc = GetDC(hwnd);
  261.    SetCapture(hwnd);
  262.    GetClientRect(hwnd, &rcClient);
  263.  
  264.    /* Get mouse coordinates relative to origin of DIB */
  265.    ptOrigin.x = GetScrollPos(hwnd, SB_HORZ);
  266.    ptOrigin.y = GetScrollPos(hwnd, SB_VERT);
  267.    pt.x += ptOrigin.x;
  268.    pt.y += ptOrigin.y;
  269.  
  270.    /* Display the coordinates */
  271.    SetWindowOrg(hdc, ptOrigin.x, ptOrigin.y);
  272.    DrawSelect(hdc, FALSE);
  273.  
  274.    /* Initialize clip rectangle to the point */
  275.    rcClip.left = pt.x;
  276.    rcClip.top = pt.y;
  277.    rcClip.right = pt.x;
  278.    rcClip.bottom = pt.y;
  279.  
  280.    /* Eat mouse messages until a WM_LBUTTONUP is encountered. Meanwhile
  281.     * continue to draw a rubberbanding rectangle and display it's dimensions
  282.     */
  283.    for (;;)
  284.    {
  285.       if (GetMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST))
  286.       {
  287.          DrawSelect(hdc, FALSE);
  288.          rcClip.left = pt.x;
  289.          rcClip.top = pt.y;
  290.          rcClip.right = LOWORD(msg.lParam) + ptOrigin.x;
  291.          rcClip.bottom = HIWORD(msg.lParam) + ptOrigin.y;
  292.          NormalizeRect(&rcClip);
  293.          DrawSelect(hdc, TRUE);
  294.          if (msg.message == WM_LBUTTONUP)
  295.             break;
  296.       }
  297.       else
  298.          continue;
  299.    }
  300.    ReleaseCapture();
  301.    ReleaseDC(hwnd, hdc);
  302. }
  303.  
  304. /****************************************************************************
  305.  *                                                                          *
  306.  *  FUNCTION   : BandDIB(HWND hWnd, HDC hDC, int x, int y)                  *
  307.  *                                                                          *
  308.  *  PURPOSE    : Outputs the DIB in bands to a device or the screen, using  *
  309.  *               the maximum possible band size.                            *
  310.  *                                                                          *
  311.  ****************************************************************************/
  312.  
  313.  
  314. void BandDIB (hWnd, hDC, x, y)
  315. HWND hWnd;
  316. HDC hDC;
  317. int x, y;
  318. {
  319.    HBITMAP hBitmap, hOld;
  320.    HDC hMemDC;
  321.    LPSTR pBuf;
  322.    LPBITMAPINFOHEADER lpbi;
  323.    WORD wRead, wActualPosition, wScansLeft;
  324.    DWORD dwMapSize;
  325.    DWORD dwScans;
  326.    WORD wBitmapHeight;
  327.    RECT Rect;
  328.    HANDLE hBuf;
  329.    BOOL bSuccess = FALSE;
  330.    WORD nBandSize;
  331.    HPALETTE hOldMemPal;
  332.    HPALETTE hOldPal;
  333.    int fh;
  334.    OFSTRUCT of;
  335.  
  336.    /* Open the map file and get the information out */
  337.  
  338.    fh = OpenFile(achFileName, (LPOFSTRUCT)&of, OF_READ);
  339.    if (fh == -1)
  340.       return;
  341.    lpbi = (VOID FAR *)GlobalLock(hbiCurrent);
  342.    if (!lpbi)
  343.    {
  344.       _lclose(fh);
  345.       return;
  346.    }
  347.  
  348.    /* Compute scan size in bytes */
  349.    dwScans = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount);
  350.    wBitmapHeight = (WORD)lpbi->biHeight;
  351.    wScansLeft = (WORD)lpbi->biHeight;
  352.    hMemDC = NULL;
  353.    for (nBandSize = wScansLeft; nBandSize >= MINBAND || nBandSize == wScansLeft
  354.         ; nBandSize -= BANDINCREMENT)
  355.    {
  356.  
  357.       /* Attempt to maximize band size by trying to allocate a buffer
  358.        * for the given band size. If allocation fails, try again with the
  359.        * smaller band size.
  360.        */
  361.       hBuf = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwScans * nBandSize);
  362.       if (!hBuf)
  363.          continue;
  364.  
  365.       /* Show success and exit loop if we're going to set bits to device. */
  366.       if (bDIBToDevice)
  367.       {
  368.          hMemDC = 1;
  369.          break;
  370.       }
  371.       else
  372.       {
  373.          /* Create a device-dependent bitmap to hold the bits */
  374.          hBitmap = CreateCompatibleBitmap(hDC, (WORD)lpbi->biWidth, nBandSize);
  375.          if (!hBitmap)
  376.          {
  377.             /* Try again for the next smaller band size */
  378.             GlobalFree(hBuf);
  379.             continue;
  380.          }
  381.  
  382.          /* Create a memory context for the bitmap */
  383.          if (!(hMemDC = CreateCompatibleDC(hDC)))
  384.          {
  385.             GlobalFree(hBuf);
  386.             DeleteObject(hBitmap);
  387.             continue;
  388.          }
  389.          else
  390.             /* Success in creating a DC */
  391.             break;
  392.       }
  393.    }
  394.    if (!hMemDC)
  395.    {
  396.  
  397.       /* We failed allocation , so give error message and quit */
  398.       if (GetFocus() == hWnd)
  399.       {
  400.          ErrMsg("No memory available!");
  401.          ValidateRect(hWnd, (LPRECT)(NULL));
  402.       }
  403.       else
  404.          MessageBeep(0);
  405.       GlobalUnlock(hbiCurrent);
  406.       _lclose(fh);
  407.       return;
  408.    }
  409.    pBuf = GlobalLock(hBuf);
  410.  
  411.    /* Calculate number of bytes to be transferred */
  412.    dwMapSize = dwScans * nBandSize;
  413.  
  414.    /* Manipulate palette appropriately */
  415.    if (!bDIBToDevice)
  416.       hOldMemPal = SelectPalette(hMemDC, hpalCurrent, 0);
  417.  
  418.    /* Now get to the start of the map in the file */
  419.    _llseek(fh, dwOffset, SEEK_SET);
  420.  
  421.    /* we are now all set to start off */
  422.    wActualPosition = wScansLeft;
  423.    Rect.left = 0;
  424.    Rect.right = (WORD)lpbi->biWidth;
  425.    hOldPal = SelectPalette(hDC, hpalCurrent, 0);
  426.    RealizePalette(hDC);
  427.    do
  428.    {
  429.       /* Read in nBandSize scans or whatever is left */
  430.       if (wScansLeft > nBandSize)
  431.          wRead = nBandSize;
  432.       else
  433.          wRead = wScansLeft;
  434.       Rect.bottom = wActualPosition;
  435.       wActualPosition -= wRead;
  436.       Rect.top = wActualPosition;
  437.       dwMapSize = ((DWORD)wRead) * dwScans;
  438.  
  439.       /* Now read in the map to the global buffer */
  440.       if (RectVisible(hDC, &Rect))
  441.       {
  442.          lread(fh, (LPSTR)pBuf, dwMapSize);
  443.          if (bDIBToDevice)
  444.          {
  445.             if (wRead != (WORD)SetDIBitsToDevice(hDC, x, y, (WORD)lpbi->biWidth
  446.                                                  , wBitmapHeight, 0, 0,
  447.                                                  wBitmapHeight - wScansLeft,
  448.                                                  wRead, pBuf, (LPBITMAPINFO)
  449.                                                  lpbi, fPalColors ?
  450.                                                  DIB_PAL_COLORS :
  451.                                                  DIB_RGB_COLORS))
  452.             {
  453.                ErrMsg("Could not draw DIB scans to device!");
  454.                GlobalUnlock(hBuf);
  455.                GlobalFree(hBuf);
  456.                GlobalUnlock(hbiCurrent);
  457.                _lclose(fh);
  458.                return;
  459.             }
  460.          }
  461.          else
  462.          {
  463.             lpbi->biHeight = wRead;
  464.  
  465.             /* Set the DIB bits to a device-dependent format */
  466.             if ((WORD)lpbi->biHeight != (WORD)SetDIBits(hMemDC, hBitmap, 0, (
  467.                                                         WORD)lpbi->biHeight,
  468.                                                         pBuf, (LPBITMAPINFO)
  469.                                                         lpbi, fPalColors ?
  470.                                                         DIB_PAL_COLORS :
  471.                                                         DIB_RGB_COLORS))
  472.             {
  473.                ErrMsg("Could not draw DIB scans!");
  474.                GlobalUnlock(hBuf);
  475.                GlobalFree(hBuf);
  476.                GlobalUnlock(hbiCurrent);
  477.                _lclose(fh);
  478.                return;
  479.             }
  480.  
  481.             /* Blt own map onto the screen, remembering the point to start */
  482.             hOld = SelectObject(hMemDC, hBitmap);
  483.             if (!BitBlt(hDC, 0, wActualPosition, (WORD)lpbi->biWidth, (WORD)
  484.                         lpbi->biHeight, hMemDC, 0, 0, SRCCOPY))
  485.             {
  486.                ErrMsg("Could not draw map to screen!");
  487.                GlobalUnlock(hBuf);
  488.                GlobalFree(hBuf);
  489.                GlobalUnlock(hbiCurrent);
  490.                _lclose(fh);
  491.                return;
  492.             }
  493.             SelectObject(hMemDC, hOld);
  494.  
  495.             /* Restore the value of bitmap height */
  496.             lpbi->biHeight = wBitmapHeight;
  497.          }
  498.       }
  499.       else
  500.       {
  501.          /* This chunk is not visible, seek over the data in the file */
  502.          _llseek(fh, dwMapSize, SEEK_CUR);
  503.       }
  504.       wScansLeft -= wRead;
  505.    } while (wScansLeft > 0);
  506.  
  507.    /* Delete the objects just created above */
  508.    GlobalUnlock(hBuf);
  509.    GlobalFree(hBuf);
  510.    SelectPalette(hDC, hOldPal, 0);
  511.  
  512.    /* Set success flag */
  513.    bSuccess = TRUE;
  514.    if (!bDIBToDevice)
  515.    {
  516.       SelectPalette(hMemDC, hOldMemPal, 0);
  517.       DeleteDC(hMemDC);
  518.       DeleteObject(hBitmap);
  519.    }
  520.    GlobalUnlock(hbiCurrent);
  521.  
  522.    /* Close the file */
  523.    _lclose(fh);
  524. }
  525.  
  526. /****************************************************************************
  527.  *                                                                          *
  528.  *  FUNCTION   : SizeWindow(HWND hWnd)                                      *
  529.  *                                                                          *
  530.  *  PURPOSE    : Sizes the app. window based on client dimensions (DIB      *
  531.  *               dimensions) and style. Sets the caption text.              *
  532.  *                                                                          *
  533.  ****************************************************************************/
  534.  
  535.  
  536. void SizeWindow (hWnd)
  537. HWND hWnd;
  538. {
  539.    char *pstr;
  540.    char Name[60];
  541.    RECT Rectangle;
  542.    BITMAPINFOHEADER bi;
  543.  
  544.    /* Get information about current DIB */
  545.  
  546.    DibInfo(hbiCurrent, &bi);
  547.  
  548.    /* Extract the filename from the full pathname */
  549.    pstr = achFileName + lstrlen(achFileName) - 1;
  550.    while ((*pstr != '\\') && (*pstr != ':') && (pstr >= achFileName))
  551.       pstr--;
  552.    pstr++;
  553.  
  554.    /* Format filename along with the DIB attributes */
  555.    wsprintf(Name, "%ls (%ls %dx%dx%d%ls)", (LPSTR)szAppName, (LPSTR)pstr, (WORD
  556.             )bi.biWidth, (WORD)bi.biHeight, (WORD)bi.biBitCount, bi.
  557.             biCompression == BI_RGB ? (LPSTR)" RGB" : bi.biCompression ==
  558.             BI_RLE8 ? (LPSTR)" RLE8" : (LPSTR)" RLE4");
  559.  
  560.    /* Show formatted text in the caption bar */
  561.    SetWindowText(hWnd, Name);
  562.  
  563.    /* Store the size in ptSize, so the scroll bars will work. */
  564.    ptSize.x = (WORD)bi.biWidth;
  565.    ptSize.y = (WORD)bi.biHeight;
  566.    if (IsZoomed(hWnd))
  567.       SetScrollRanges(hWnd);
  568.    else
  569.    {
  570.       Rectangle.left = 0;
  571.       Rectangle.top = 0;
  572.       Rectangle.right = (WORD)bi.biWidth;
  573.       Rectangle.bottom = (WORD)bi.biHeight;
  574.  
  575.       /* Compute the size of the window rectangle based on the given
  576.        * client rectangle size and the window style, then size the
  577.        * window.
  578.        */
  579.       AdjustWindowRect(&Rectangle, dwStyle, TRUE);
  580.       SetWindowPos(hWnd, (HWND)NULL, 0, 0, Rectangle.right - Rectangle.left + 1
  581.                    , Rectangle.bottom - Rectangle.top + 1, SWP_NOMOVE |
  582.                    SWP_NOZORDER);
  583.    }
  584.    InvalidateRect(hWnd, NULL, TRUE);
  585. }
  586.  
  587. /****************************************************************************
  588.  *                                                                          *
  589.  *  FUNCTION   : GetRealClientRect(HWND hwnd, LPRECT lprc)                  *
  590.  *                                                                          *
  591.  *  PURPOSE    : Calculates the client rectangle taking scrollbars into     *
  592.  *               consideration.                                             *
  593.  *                                                                          *
  594.  ****************************************************************************/
  595.  
  596.  
  597. void GetRealClientRect (hwnd, lprc)
  598. HWND hwnd;
  599. PRECT lprc;
  600. {
  601.    DWORD dwStyle;
  602.  
  603.    dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  604.    GetClientRect(hwnd, lprc);
  605.    if (dwStyle & WS_HSCROLL)
  606.       lprc->bottom += GetSystemMetrics(SM_CYHSCROLL);
  607.    if (dwStyle & WS_VSCROLL)
  608.       lprc->right += GetSystemMetrics(SM_CXVSCROLL);
  609. }
  610.  
  611. /****************************************************************************
  612.  *                                                                          *
  613.  *  FUNCTION   : SetScrollRanges(hwnd)                                      *
  614.  *                                                                          *
  615.  *  PURPOSE    :                                                            *
  616.  *                                                                          *
  617.  ****************************************************************************/
  618.  
  619.  
  620. void SetScrollRanges (hwnd)
  621. HWND hwnd;
  622. {
  623.    RECT rc;
  624.    int iRangeH, iRangeV, i;
  625.    static int iSem = 0;
  626.  
  627.    if (!iSem)
  628.    {
  629.       iSem++;
  630.       GetRealClientRect(hwnd, &rc);
  631.       for (i = 0; i < 2; i++)
  632.       {
  633.          iRangeV = ptSize.y - rc.bottom;
  634.          iRangeH = ptSize.x - rc.right;
  635.          if (iRangeH < 0)
  636.             iRangeH = 0;
  637.          if (iRangeV < 0)
  638.             iRangeV = 0;
  639.          if (GetScrollPos(hwnd, SB_VERT) > iRangeV || GetScrollPos(hwnd,
  640.                                                                    SB_HORZ) >
  641.              iRangeH)
  642.             InvalidateRect(hwnd, NULL, TRUE);
  643.          SetScrollRange(hwnd, SB_VERT, 0, iRangeV, TRUE);
  644.          SetScrollRange(hwnd, SB_HORZ, 0, iRangeH, TRUE);
  645.          GetClientRect(hwnd, &rc);
  646.       }
  647.       iSem--;
  648.    }
  649. }
  650.  
  651. /*********** THE FOLLOWING FUNCTIONS ARE FOR CLIPBOARD SUPPORT **************/
  652. /****************************************************************************
  653.  *                                                                          *
  654.  *  FUNCTION   : CopyHandle (HANDLE h)                                      *
  655.  *                                                                          *
  656.  *  PURPOSE    : Makes a copy of the given global memory block.             *
  657.  *                                                                          *
  658.  *  RETURNS    : A handle to the new block.                                 *
  659.  *                                                                          *
  660.  ****************************************************************************/
  661.  
  662.  
  663. HANDLE CopyHandle (h)
  664. HANDLE h;
  665. {
  666.    BYTE huge *lpCopy;
  667.    BYTE huge *lp;
  668.    HANDLE hCopy;
  669.    DWORD dwLen;
  670.  
  671.    dwLen = GlobalSize(h);
  672.    if (hCopy = GlobalAlloc(GHND, dwLen))
  673.    {
  674.       lpCopy = (BYTE huge *)GlobalLock(hCopy);
  675.       lp = (BYTE huge *)GlobalLock(h);
  676.       while (dwLen--)
  677.          *lpCopy++ = *lp++;
  678.       GlobalUnlock(hCopy);
  679.       GlobalUnlock(h);
  680.    }
  681.    return hCopy;
  682. }
  683.  
  684. /****************************************************************************
  685.  *                                                                          *
  686.  *  FUNCTION   : CopyPalette(HPALETTE hpal)                                 *
  687.  *                                                                          *
  688.  *  PURPOSE    : Makes a copy of a GDI logical palette                      *
  689.  *                                                                          *
  690.  *  RETURNS    : A handle to the new palette.                               *
  691.  *                                                                          *
  692.  ****************************************************************************/
  693.  
  694.  
  695. HPALETTE CopyPalette (hpal)
  696. HPALETTE hpal;
  697. {
  698.    PLOGPALETTE ppal;
  699.    int nNumEntries;
  700.  
  701.    if (!hpal)
  702.       return NULL;
  703.    GetObject(hpal, sizeof(int), (LPSTR)&nNumEntries);
  704.    if (nNumEntries == 0)
  705.       return NULL;
  706.    ppal = (PLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE) + nNumEntries *
  707.                                   sizeof(PALETTEENTRY));
  708.    if (!ppal)
  709.       return NULL;
  710.    ppal->palVersion = PALVERSION;
  711.    ppal->palNumEntries = nNumEntries;
  712.    GetPaletteEntries(hpal, 0, nNumEntries, ppal->palPalEntry);
  713.    hpal = CreatePalette(ppal);
  714.    LocalFree((HANDLE)ppal);
  715.    return hpal;
  716. }
  717. /****************************************************************************
  718.  *                                                                          *
  719.  *  FUNCTION   : CopyBitmap (HBITMAP hbm)                                   *
  720.  *                                                                          *
  721.  *  PURPOSE    : Copies the given bitmap to another.                        *
  722.  *                                                                          *
  723.  *  RETURNS    : A handle to the new bitmap.                                *
  724.  *                                                                          *
  725.  ****************************************************************************/
  726.  
  727.  
  728. HBITMAP CopyBitmap (hbm)
  729. HBITMAP hbm;
  730. {
  731.    BITMAP bm;
  732.    RECT rc;
  733.  
  734.    if (!hbm)
  735.       return NULL;
  736.    GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm);
  737.    rc.left = 0;
  738.    rc.top = 0;
  739.    rc.right = bm.bmWidth;
  740.    rc.bottom = bm.bmHeight;
  741.    return CropBitmap(hbm, &rc);
  742. }
  743. /****************************************************************************
  744.  *                                                                          *
  745.  *  FUNCTION   :  CropBitmap (hbm,lprect)                                   *
  746.  *                                                                          *
  747.  *  PURPOSE    :  Crops a bitmap to a new size specified by the lprect      *
  748.  *                parameter.                                                *
  749.  *                                                                          *
  750.  *  RETURNS    :  A handle to the new bitmap.                               *
  751.  *                                                                          *
  752.  ****************************************************************************/
  753.  
  754.  
  755. HBITMAP CropBitmap (hbm, prc)
  756. HBITMAP hbm;
  757. PRECT prc;
  758. {
  759.    HDC hMemDCsrc;
  760.    HDC hMemDCdst;
  761.    HDC hdc;
  762.    HBITMAP hNewBm;
  763.    BITMAP bm;
  764.    int dx, dy;
  765.  
  766.    if (!hbm)
  767.       return NULL;
  768.    hdc = GetDC(NULL);
  769.    hMemDCsrc = CreateCompatibleDC(hdc);
  770.    hMemDCdst = CreateCompatibleDC(hdc);
  771.    GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm);
  772.    dx = prc->right - prc->left;
  773.    dy = prc->bottom - prc->top;
  774.    hNewBm = CreateBitmap(dx, dy, bm.bmPlanes, bm.bmBitsPixel, NULL);
  775.    if (hNewBm)
  776.    {
  777.       SelectObject(hMemDCsrc, hbm);
  778.       SelectObject(hMemDCdst, hNewBm);
  779.       BitBlt(hMemDCdst, 0, 0, dx, dy, hMemDCsrc, prc->left, prc->top, SRCCOPY);
  780.    }
  781.    ReleaseDC(NULL, hdc);
  782.    DeleteDC(hMemDCsrc);
  783.    DeleteDC(hMemDCdst);
  784.    return hNewBm;
  785. }
  786.  
  787. /****************************************************************************
  788.  *                                                                          *
  789.  *  FUNCTION   : RenderFormat(int cf)                                       *
  790.  *                                                                          *
  791.  *  PURPOSE    : Renders the currently displayed DIB in CF_DIB or           *
  792.  *               CF_BITMAP format.The bitmap is clipped to the current      *
  793.  *               rcClip.                                                    *
  794.  *                                                                          *
  795.  *  RETURNS    : A handle to the DIB                                        *
  796.  *                                                                          *
  797.  ****************************************************************************/
  798.  
  799.  
  800. HANDLE RenderFormat (cf)
  801. int cf;
  802. {
  803.    HANDLE h = NULL;
  804.    HBITMAP hbm;
  805.  
  806.    if (!bLegitDraw)
  807.       return NULL;
  808.    switch (cf)
  809.       {
  810.    case CF_BITMAP:
  811.       if (hbmCurrent && !IsRectEmpty(&rcClip))
  812.          h = CropBitmap(hbmCurrent, &rcClip);
  813.       else
  814.       {
  815.          if (hbmCurrent)
  816.             h = CopyBitmap(hbmCurrent);
  817.          else if (hdibCurrent)
  818.             h = BitmapFromDib(hdibCurrent, hpalCurrent);
  819.          else if (achFileName[0] && (hdibCurrent = OpenDIB(achFileName)))
  820.             h = BitmapFromDib(hdibCurrent, hpalCurrent);
  821.          else
  822.             h = NULL;
  823.          if (h && !IsRectEmpty(&rcClip))
  824.          {
  825.             hbm = CropBitmap(h, &rcClip);
  826.             DeleteObject(h);
  827.             h = hbm;
  828.          }
  829.       }
  830.       break;
  831.  
  832.    case CF_DIB:
  833.       if (!IsRectEmpty(&rcClip))
  834.       {
  835.          if (hbm = RenderFormat(CF_BITMAP))
  836.          {
  837.             h = DibFromBitmap(hbm, BI_RGB, 0, hpalCurrent);
  838.             DeleteObject(hbm);
  839.          }
  840.       }
  841.       else
  842.       {
  843.          if (!hdibCurrent && hbmCurrent)
  844.             h = DibFromBitmap(hbmCurrent, BI_RGB, 0, hpalCurrent);
  845.          else if (hdibCurrent)
  846.             h = CopyHandle(hdibCurrent);
  847.          else if (achFileName[0])
  848.             h = OpenDIB(achFileName);
  849.          else
  850.             h = NULL;
  851.       }
  852.       break;
  853.  
  854.    case CF_PALETTE:
  855.       if (hpalCurrent)
  856.          h = CopyPalette(hpalCurrent);
  857.       break;
  858.       }
  859.    return h;
  860. }
  861. /****************************************************************************
  862.  *                                                                          *
  863.  *  FUNCTION   :  RealizeDibFormat(DWORD biStyle, WORD biBits)              *
  864.  *                                                                          *
  865.  *  PURPOSE    :  Realize the current DIB in the specifed format            *
  866.  *                This function is used to get a specific format of CF_DIB  *
  867.  *                                                                          *
  868.  *                    biStyle     DIB format      RGB or RLE                *
  869.  *                    biBits      Bits per pixel  1,4,8,24                  *
  870.  *                                                                          *
  871.  *  RETURNS    :  A handle to the created DIB.                              *
  872.  *                                                                          *
  873.  ****************************************************************************/
  874.  
  875.  
  876. HANDLE RealizeDibFormat (biStyle, biBits)
  877. DWORD biStyle;
  878. WORD biBits;
  879. {
  880.    BITMAPINFOHEADER bi;
  881.  
  882.    if (!bLegitDraw)
  883.       return NULL;
  884.    DibInfo(hbiCurrent, &bi);
  885.  
  886.    /*  Do we have the requested format already? */
  887.    if (bi.biCompression == biStyle && bi.biBitCount == biBits)
  888.    {
  889.       if (!hdibCurrent)
  890.          hdibCurrent = RenderFormat(CF_DIB);
  891.    }
  892.    else
  893.    {
  894.       if (!hbmCurrent)
  895.          hbmCurrent = RenderFormat(CF_BITMAP);
  896.       if (hbmCurrent)
  897.       {
  898.          if (hdibCurrent)
  899.             GlobalFree(hdibCurrent);
  900.          hdibCurrent = DibFromBitmap(hbmCurrent, biStyle, biBits, hpalCurrent);
  901.       }
  902.    }
  903.    return hdibCurrent;
  904. }
  905. /****************************************************************************
  906.  *                                                                          *
  907.  *  FUNCTION   : ErrMsg (PSTR sz,...)                                       *
  908.  *                                                                          *
  909.  *  PURPOSE    : Opens a Message box with a error message in it.The user can*
  910.  *               select the OK button to continue                           *
  911.  *                                                                          *
  912.  *  RETURNS    : FALSE to indicate an error has occured.                    *
  913.  *                                                                          *
  914.  ****************************************************************************/
  915.  
  916.  
  917. int ErrMsg (PSTR sz, ...)
  918. {
  919.    char ach[128];
  920.  
  921.    wvsprintf(ach, sz, (LPSTR)(&sz + 1));   /* Format the string */
  922.    MessageBox(NULL, ach, NULL, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  923.    return FALSE;
  924. }
  925.  
  926. /****************************************************************************
  927.  *                                                                          *
  928.  *  FUNCTION   : fDialog(int id,HWND hwnd,FARPROC fpfn)                     *
  929.  *                                                                          *
  930.  *  PURPOSE    : This function displays a dialog box                        *
  931.  *                                                                          *
  932.  *  RETURNS    : The exit code.                                             *
  933.  *                                                                          *
  934.  ****************************************************************************/
  935.  
  936.  
  937. BOOL fDialog (id, hwnd, fpfn)
  938. int id;
  939. HWND hwnd;
  940. FARPROC fpfn;
  941. {
  942.    BOOL f;
  943.    HANDLE hInst;
  944.  
  945.    hInst = GetWindowWord(hwnd, GWW_HINSTANCE);
  946.    fpfn = MakeProcInstance(fpfn, hInst);
  947.    f = DialogBox(hInst, MAKEINTRESOURCE(id), hwnd, fpfn);
  948.    FreeProcInstance(fpfn);
  949.    return f;
  950. }
  951.  
  952. /****************************************************************************
  953.  *                                                                          *
  954.  *  FUNCTION   : AppAbout( hDlg, uiMessage, wParam, lParam )                *
  955.  *                                                                          *
  956.  *  PURPOSE    : Dialog function for the About... dialog box                *
  957.  *                                                                          *
  958.  ****************************************************************************/
  959.  
  960.  
  961. BOOL FAR PASCAL AppAbout (hDlg, uiMessage, wParam, lParam)
  962. HWND hDlg;
  963. unsigned uiMessage;
  964. WORD wParam;
  965. long lParam;
  966. {
  967.    switch (uiMessage)
  968.       {
  969.    case WM_COMMAND:
  970.       if (wParam == IDOK)
  971.          EndDialog(hDlg, TRUE);
  972.       break;
  973.  
  974.    case WM_INITDIALOG:
  975.       return TRUE;
  976.       }
  977.    return FALSE;
  978. }
  979.